<style src="./index.scss" lang="scss" scoped></style>
<template>
    <div class="city-no-relation-box">
        <el-cascader
            v-model="optionValue"
            ref="cascaderRef"
            collapse-tags
            :options="options"
            :placeholder="placeholder"
            :clearable="clearable"
            @change="handleChange"
            :props="cascaderProps"
        >
        </el-cascader>
    </div>
</template>

<script lang="ts">
import { Component, Mixins, Prop } from "vue-property-decorator";
import FormMixin from "@/mixins/form.mixin.base.ts";
import { State } from 'vuex-class';
import { isObject, listToTree, merge, treeFindPath } from '@/utils';

@Component({
    model: {
        prop: "value",
        event: "change"
    },
    components: {
    }
})
export default class CityNoRelation extends Mixins(FormMixin) {
    @State(state => state.user.userInfo) user: any;
    @Prop({
        type: Array,
        default: () => {
            return [];
        }
    })
    readonly value!: any[];

    // 可以传递ids用于数据回显
    // ids 是id，value，label之类的值，以下统称id
    // ids 代表的是每个选项项的最后一级的id，当存在多项一样的时候会返回匹配到的第一项
    ids: any[] = [];

    // idsKey 决定上面的ids是用的哪个字段作为key，默认是id
    @Prop({
        type: String,
        default: "id"
    })
    readonly idsKey!: string;

    @Prop({
        type: Boolean,
        default: false
    })
    readonly multiple!: boolean;

    @Prop({
        type: Boolean,
        default: false
    })
    readonly clearable!: boolean;

    @Prop({
        type: Boolean,
        default: false
    })
    readonly showOperate!: boolean;// 是否需要在第一级追加运营专区选项

    // notAuth 代表不需要根据用户权限拉取
    // auth代表需要
    // authNoVillage代表需要,并且不会返回村信息
    @Prop({
        type: String,
        default: "notAuth"
    })
    readonly cityQuery!: string;

    @Prop({
        type: String,
        default: "请选择区域"
    })
    readonly placeholder!: string;

    @Prop({
        type: Number,
        default: 5
    })
    readonly showIndex!: number;

    @Prop({
        type: Function,
        default: () => {
            return null;
        }
    })
    readonly afterInitAuthData!: any;

    get optionValue() {
        // console.log('getValue', this.value);
        return this.value;
    }

    set optionValue(val: any) {
        // console.log("change", val);
        this.$emit("change", val);
    }

    get cascaderProps() {
        return {
            checkStrictly: true,
            multiple: this.multiple,
            lazy: true,
            lazyLoad: (node: any, resolve: any) => {
                const { value, level } = node;
                this.initData(value || "", level, level === 0).then((res: any[]) => {
                    if (node.children && node.children.length > 0) {
                        const nRes: any[] = res.filter((_r: any) => {
                            return node.children.findIndex((cur: any) => cur.value === _r.value) === -1;
                        });
                        resolve(nRes);
                    } else {
                        resolve(res);
                    }
                });
            }
        };
    }

    get userLevel() {
        return this.$getUserLevel(this.user ? this.user.orgCategoryId || "" : "");
    }

    get isVillage() {
        const village: any[] = ["VILLAGE_ADMIN", "VILLAGE"];
        return village.includes(this.userLevel.name);
    }

    get isTown() {
        const town: any[] = ["TOWN_ADMIN", "TOWN"];
        return town.includes(this.userLevel.name);
    }

    get disabledIndex() {
        if (this.isVillage) {
            return 3;
        } else if (this.isTown) {
            return 2;
        } else {
            return 1;
        }
    }

    authOptions: any[] = [];
    options: any[] = [];

    created() {
        this.initAuthData();
    }

    handleChange() {
        // this.$store.dispatch("updateAuthArea", {
        //     governmentId: 1,
        //     departmentId: 2,
        //     orgCategoryId: 3
        // });
        this.$nextTick(() => {
            const cascaderRef: any = this.$refs.cascaderRef;
            this.$emit("area-change", this.optionValue, cascaderRef.getCheckedNodes());
        });
    }


    async getDataList(code?: any) {
        let url = "";
        if (this.cityQuery === "auth") {
            url = "cityQueryAuth";
        } else if (this.cityQuery === "authNoVillage") {
            url = "cityQueryAuthNoVillage";
        } else {
            url = "cityQuery";
        }
        let data: any = {};
        data = {
            code: code || ""
        };
        const response = await this.$server[url]({
            loader: false,
            data
        });
        if (this.responseHasError(response)) {
            return [];
        }
        return response.data.data;
    }

    async handleAuthData() {
        if (this.cityQuery !== "auth" && this.cityQuery !== "authNoVillage") return;
        await this.handleAuthLink();
        this.handleDefaultValue();
        const dataResponse = await this.initData("", 0, false);
        this.options = dataResponse;
    }

    async initAuthData() {
        if (this.cityQuery !== "auth" && this.cityQuery !== "authNoVillage") return;
        await this.handleAuthData();
        this.afterInitAuthData(this.options);
    }

    async handleAuthLink() {
        if (this.ids.length === 0) return;
        const response = await this.getSelectList(this.ids);
        // const response = [{
        //     province: {
        //         id: "1",
        //         name: "北京市",
        //         code: 110000
        //     },
        //     city: {
        //         id: "2",
        //         name: "北京市2",
        //         code: 2224
        //     },
        //     area: {
        //         id: "4",
        //         name: "北京市4",
        //         code: 22264
        //     },
        //     town: {
        //         id: "5",
        //         name: "北京市5",
        //         code: 22265
        //     },
        //     village: {
        //         id: "6",
        //         name: "北京市6",
        //         code: 22266
        //     }
        // }];
        let option: any = [];
        for (let j = 0; j < response.length; j++) {
            const curRes = response[j];
            if (isObject(curRes)) {
                const list: any[] = ["province", "city", "area", "town", "village"];
                const town: any[] = ["TOWN_ADMIN", "TOWN"];
                const village: any[] = ["VILLAGE_ADMIN", "VILLAGE"];
                const status: any = this.$getUserLevel(this.user ? this.user.orgCategoryId || "" : "");
                const _option: any = [];
                let disabledIndex = 1;
                if (town.includes(status.name)) {
                    disabledIndex = 2;
                }
                if (village.includes(status.name)) {
                    disabledIndex = 3;
                }
                for (let i = 0; i < list.length; i++) {
                    const cur = list[i];
                    const _rCur = curRes[cur];
                    if (_rCur && _rCur.id) {
                        _option[i] = {
                            parentId: i === 0 ? null : _option[i - 1].value,
                            label: _rCur.name,
                            id: _rCur.id || "",
                            value: _rCur.code + "",
                            disabled: i <= disabledIndex,
                            leaf: (i + 1) >= this.showIndex || i === list.length - 1
                        };
                    } else {
                        if (i !== 0) {
                            // _option[i - 1].leaf = true;
                        }
                        break;
                    }
                }
                option = option.concat(_option.filter((cur: any) => {
                    const _oI: any = option.findIndex((oCur: any) => cur.value === oCur.value);
                    if (_oI === -1) {
                        return true;
                    } else {
                        option[_oI] = cur;
                        return false;
                    }
                    // return option.findIndex((oCur: any) => cur.value === oCur.value) === -1;
                }));
            }
        }
        this.authOptions = listToTree(option);
        return response;
    }

    async getSelectList(ids: any[]) {
        const url = "cityAuthLink";
        // let data: any[] = [];
        // data = (ids || []).map((cur: any) => {
        //     return Number(cur);
        // });
        let data: any = {};
        data = {
            governmentIds: ids || []
        };
        const response = await this.$server[url]({
            loader: false,
            data
        });
        if (this.responseHasError(response)) {
            return [];
        }
        return response.data.data;
    }

    handleDefaultValue() {
        if (this.ids.length !== 0) {
            const _path = treeFindPath(this.authOptions, (node: any) => {
                return this.ids.includes(node[this.idsKey]);
            }, {
                multiple: this.multiple
            });
            this.optionValue = _path;
        }
        this.$nextTick(() => {
            this.valueChangeBuildOption();
        });
    }

    getOperationItem() {
        if (!this.showOperate) {
            return null;
        }
        const status: any = this.$getUserLevel(this.user ? this.user.orgCategoryId || "" : "");
        // console.log(status);
        if (["OPERATION", "OPERATION_ADMIN", "ADMIN"].includes(status.name)) {
            return {
                label: "运营专区",
                id: "0",
                value: "0",
                leaf: true
            };
        }
        return null;
    }

    async initData(cityCode: any, level: any, stop: boolean) {
        if (stop) return [];
        const response = await this.getDataList(cityCode);
        const list: any[] = response.map((cur: any) => {
            let subChidlren: any = [];
            if (level === 0) {
                const _index = this.authOptions.findIndex((aCur: any) => aCur.value === cur.code + "");
                if (_index !== -1) {
                    subChidlren = this.authOptions[_index].children;
                }
            }
            return {
                children: subChidlren,
                label: cur.name,
                id: cur.id || "",
                value: cur.code + "",
                disabled: level <= this.disabledIndex || !cur.option,
                leaf: (level + 1) >= this.showIndex || (cur.code + "").length >= 16
            };
        });
        if (level === 0) {
            const item: any = this.getOperationItem();
            item && list.unshift(item);
        }
        return list;
    }

    _findIdRelation(ids: any[], key?: string, _returnKey?: string) {
        const _key = key || "value";
        const res: any[] = this.findIdRelation(ids, this.options, _key, _returnKey || _key);
        return this.multiple ? res : res[0] || [];
    }

    async setIds(ids: any[]) {
        this.ids = merge(true, [], ids);
        this.handleAuthData();
    }

    valueChangeBuildOption() {
        const _value = this.multiple ? this.optionValue[0] || [] : this.optionValue || [];
        if (_value.length === 0) return;
        const allP: any[] = [];
        _value.forEach((cur: any, index: any) => {
            allP.push(this.initData(cur, index + 1, false));
        });
        const changOptionChildren = (list: any[], resList: any[], index: any) => {
            for (let i = 0; i < list.length; i++) {
                const cur = list[i];
                if (!cur.children) {
                    cur.children = [];
                }
                if (cur.value === _value[index] && resList[index]) {
                    cur.children = cur.children.concat(resList[index].filter((rCur: any) => {
                        return cur.children.findIndex((oCur: any) => rCur.value === oCur.value) === -1;
                    }));
                    changOptionChildren(cur.children, resList, index + 1);
                    break;
                }
            }
            return list;
        };
        Promise.all(allP).then((resList: any[]) => {
            // console.log('this.options', this.options);
            changOptionChildren(this.options, resList, 0);
        });
    }
}
</script>
